module cache_groups
(
	input clk,
	input [63:0] renew_data,
	input [7:0] addr,
	input write_enable,
	output hit,
	output [31:0] read_from_group,
	output [31:0] another_half,
	output if_changed,
	output [6:0] changed_addr,
	output [63:0] changed_data,

	input [7:0] pdu_addr,
	output pdu_hit,
	output [31:0] read_for_pdu
);
//组集线器
wire [31:0]out0,out1,out2,out3;//各组输出数据
wire [31:0]ano0,ano1,ano2,ano3;
wire hit0,hit1,hit2,hit3;//各组是否命中
wire changed0,changed1,changed2,changed3;//各组是否需要行替换
wire [4:0]changed_tag_0,changed_tag_1,changed_tag_2,changed_tag_3;//行替换的位置
wire [63:0]changed_data_0,changed_data_1,changed_data_2,changed_data_3;//行替换的输出数据
wire [31:0]pdu_out0,pdu_out1,pdu_out2,pdu_out3;
wire pdu_hit0,pdu_hit1,pdu_hit2,pdu_hit3;

assign read_from_group=out0|out1|out2|out3;
assign hit=hit0|hit1|hit2|hit3;
assign if_changed=changed0|changed1|changed2|changed3;
assign changed_data=changed_data_0|changed_data_1|changed_data_2|changed_data_3;
assign read_for_pdu=pdu_out0|pdu_out1|pdu_out2|pdu_out3;
assign pdu_hit=pdu_hit0|pdu_hit1|pdu_hit2|pdu_hit3;

wire [1:0]changed_group_num;
wire [4:0]changed_tag;
assign changed_group_num=changed0?2'd0:(changed1?2'd1:(changed2?2'd2:changed_data_3?2'd3:0));
assign changed_tag=changed_tag_0|changed_tag_1|changed_tag_2|changed_tag_3;
assign changed_addr=if_changed?{changed_tag,changed_group_num}:7'b0;//行替换的地址
assign another_half=ano0|ano1|ano2|ano3;

cache_group #(0)group0(
	.clk(clk),
	.id(addr[2:1]),
	.renew_data(renew_data),
	.tag(addr[7:3]),
	.offset(addr[0]),
	.write_enable(write_enable),
	.hit(hit0),
	.read_from_group(out0),
	.another_half(ano0),
	.if_changed(changed0),
	.changed_tag(changed_tag_0),
	.changed_data(changed_data_0),
	.pdu_addr(pdu_addr),
	.pdu_hit(pdu_hit0),
	.read_for_pdu(pdu_out0)
);

cache_group #(1)group1(
	.clk(clk),
	.id(addr[2:1]),
	.renew_data(renew_data),
	.tag(addr[7:3]),
	.offset(addr[0]),
	.write_enable(write_enable),
	.hit(hit1),
	.read_from_group(out1),
	.another_half(ano1),
	.if_changed(changed1),
	.changed_tag(changed_tag_1),
	.changed_data(changed_data_1),
	.pdu_addr(pdu_addr),
	.pdu_hit(pdu_hit1),
	.read_for_pdu(pdu_out1)
);

cache_group #(2)group2(
	.clk(clk),
	.id(addr[2:1]),
	.renew_data(renew_data),
	.tag(addr[7:3]),
	.offset(addr[0]),
	.write_enable(write_enable),
	.hit(hit2),
	.read_from_group(out2),
	.another_half(ano2),
	.if_changed(changed2),
	.changed_tag(changed_tag_2),
	.changed_data(changed_data_2),
	.pdu_addr(pdu_addr),
	.pdu_hit2(pdu_hit2),
	.read_for_pdu(pdu_out2)
);

cache_group #(3)group3(
	.clk(clk),
	.id(addr[2:1]),
	.renew_data(renew_data),
	.tag(addr[7:3]),
	.offset(addr[0]),
	.write_enable(write_enable),
	.hit(hit3),
	.read_from_group(out3),
	.another_half(ano3),
	.if_changed(changed3),
	.changed_tag(changed_tag_3),
	.changed_data(changed_data_3),
	.pdu_addr(pdu_addr),
	.pdu_hit(pdu_hit3),
	.read_for_pdu(pdu_out3)
);

endmodule